﻿import re, datetime
import htmllib, formatter, urllib
import StringIO
from BeautifulSoup import BeautifulSoup


#from vapi.person.models import Person
#from vapi.event.models import Event

class SomeParser(object):
    
    base_url = ""

    def text_extractor(self, html):
        # Функция выдирает из html весь текст, если там были ссылки
        # то дает на них сноски и перечесляет списком их внизу
        # create memory file
        file = StringIO.StringIO()
        # convert html to text
        f = formatter.AbstractFormatter(formatter.DumbWriter(file))
        p = htmllib.HTMLParser(f)
        p.feed(html)
        p.close()
        if p.anchorlist:
            file.write("\n\nlinks:\n")
            i = 1
            for anchor in p.anchorlist:
                file.write("%d: %s\n" % (i, anchor))
                i = i + 1
        text = file.getvalue()
        return text
    
    def get_image(self, url, file):
     
        if not file:
            localFile = open(url.split('/')[-1], 'w')
        else:
            localFile = open(file, 'w')
        urllib.urlretrieve(url, localFile)

class VkontakteNewsParser(SomeParser):
    
    def __init__(self, html):
        self.soup = BeautifulSoup(html)
    
    def check_marked(self):
        pass
    
    def parse(self, lines):
        # Перекидываем страницу в строчку
        #Тут еще нужна оболочка по дате        
        # Парсим блоки и их тип. По типу допарсиваем конечные данные
        
        
        days = self.soup.findAll("div","feedDay")
        
        for day in days:
            news_table = day.parent.findNextSibling("div", style="padding:10px 10px 20px 10px;").findAll("table","feedTable")
            for news in news_table:
                news_type = news.find("img","feedIcon").attrs[1][1].split("/")[-1].split("_")[0]
                story = news.find("td","feedStory").renderContents().rstrip().lstrip()
                author = news.find("td","feedStory").a.contents[0]
                author_id = news.find("td","feedStory").a.attrs[0][1][2:]
                time = news.find("td","feedTime").contents[0]
                if day == u"Сегодня":
                    date = str(datetime.date.today())
                if day == u"Вчера":
                    date = str(datetime.date.today() - datetime.timedelta(1))
                else:
                    date = day
          

class VkontakteProfileParser(SomeParser):
    
    hided_file = "e:/hided_friends.list"
    
    def __init__(self, html):
        self.soup = BeautifulSoup(html)
    
    def get_idnum(self):
        # TODO
        # Возвращает idnum, сейчас годится только для хозяйской анкеты, да и то под вопросом
        
        # Получаем id хозяйской анкеты и вообще анкеты по пасу к аватару
        try:
            idnum=str(self.soup.find('div', id="leftColumn").div.img).split('/')[3][1:]
        except:
            raise Exception('Cant find id in profile, fix code')
        return idnum
    
    def check_error(self):
        # Проверка на залогиненность, удаленность и закрытость
        # Актуально когда дойду до парсенья френдов
        error = self.soup.find('div', id='error').contents[0]
        if ("пароль неверный" in error):
            raise Exception('Wrong password')
        return True
        # Проверка на доступность анкеты
#        if re.search('<div style=[^>]*>\s*Страница удалена, либо еще не создана.\s*</div>',lines):
#            return self.parse_info(html=lines, status="deleted", id=idnum)
#        elif re.search('<dd><span class=\'bbb\'>Страница удалена</span></dd>',lines):
#            return self.parse_info(html=lines, status="deleted", id=idnum)
#        elif re.search('<div class=\"info\">\s*<dl class=\"clearFix\">\s*<dt>Имя:</dt>',lines):
#            return self.parse_info(html=lines, status="closed", id=idnum)
    
    def check_online(self):
        # Проверяет онлайн ли юзер. Возвращет булево значение
        if self.soup.find('div', id="header").h1.b.contents[0] == u'Online':
            return True
        else:
            return False
        
    def parse_profile(self):
        # Базовый парсинг
        
        # Ищем idnum по ссылке на картинку
        idnum = self.get_idnum()
        
        # TODO нормально разобраться с исключениями
        try:
            self.check_error()
        except:
            return Exception
        
        # Получаем имя, ник и фамилию
        name = self.soup.find('div', 'profileName').h2.contents[0].split(' ')[0]
        surname = self.soup.find('div', 'profileName').h2.contents[0].split(' ')[-1]
        nick = self.soup.find('div', 'profileName').h2.contents[0].split(' ')[1:-1]
        fullname = name + surname
        
        # Создаем из значений словарь и тошним его наружу
        pdata={ "idnum" : idnum, 
               "name" : name, 
               "surname" : surname, 
               "nickname" : nick,
               "fullname" : fullname, }
        return pdata
        
    def parse_groups(self):
        # Парсим группы в контакте
        # Ищем по строчке:
        # <a href=\'club(?P<idnum>\d*)\'>(?P<name>[^<]*)</a>
        group_list = self.soup.findAll('a', href=re.compile("^club"))
        groups = []
        for group in group_list:
            group_idnum = group.attrs[0][1][4:]
            title = group.contents[0]
            groups.append({
                           'group_idnum':group_idnum,
                           'title':title
                           })
        return groups
    
    def parse_status_history(self):
        # Функция вытаскивает историю статуса из чужих анкет
        # ajax getActivityHistory(idnum)
        pass
    
    def parse_status(self):
        # Функци вытаскивает статус, независимо от того, своя анкета или чужая
        # Парсим по "<span id=\"activity_text\"[*>]*>(?P<status>[^<]*)</span"
        status = self.soup.find("span", id="activity_text").contents[0]
        return status
    
    def parse_basic_info(self):
        # Функция парсит базовые данные анкеты
        # Как то:
        # пол, семейный статус, дата рождения
        
        basics = self.soup.find("div", "basicInfo").table.findAll("tr")
        me = {}
        links = {}
        for base in basics:
            label = base.find("td","label").contents[0][:-1]
            value = unicode(base.find("div","dataWrap").a.contents[0])
            link = base.find("div","dataWrap").a.attrs[0][1]
            me[label] = value
            links[label] = link
            print "%s\t%s\t%s\n" % (str(label.encode('cp1251')), str(link.encode('cp1251')), str(value.encode('cp1251')))
        return me, links

    def parse_contact_info(self):
        # Функция парсит базовые данные анкеты
        # Как то:
        # пол, семейный статус, дата рождения
        
        basics = self.soup.find("div", id="personal").table.findAll("tr")
        me = {}
        links = {}
        for base in basics:
            label = base.find("td","label").contents[0][:-1]
            try:
                check = base.find("div","dataWrap").a.contents[0]
            except:
                check = False
            if check:
                value = unicode(check)
                link = base.find("div","dataWrap").a.attrs[0][1]
            else:
                value = unicode(base.find("div","dataWrap").contents[0])
                link = ""
            me[label] = value
            links[label] = link
            print "%s\t%s\t%s\n" % (str(label.encode('cp1251')), str(link.encode('cp1251')), str(value.encode('cp1251')))
        return me, links
    
    def parse_education_info(self):
        # Функция парсит базовые данные анкеты
        # Как то:
        # пол, семейный статус, дата рождения
        
        basics = self.soup.find("div", id="education").table.findAll("tr")
        me = {}
        links = {}
        for base in basics:
            label = base.find("td","label").contents[0][:-1]
            try:
                check = base.find("div","dataWrap").a.contents[0]
            except:
                check = False
            if check:
                value = unicode(check)
                link = base.find("div","dataWrap").a.attrs[0][1]
            else:
                value = unicode(base.find("div","dataWrap").contents[0])
                link = ""
            me[label] = value
            links[label] = link
            print "%s\t%s\t%s\n" % (str(label.encode('cp1251')), str(link.encode('cp1251')), str(value.encode('cp1251')))
        return me, links




p = VkontakteProfileParser(open("c:/a.html","r").read().decode("cp1251").encode("utf8"))
p.parse_personal_info()      
        
#        # Парсим универ
#        m=re.compile('<a href=\'search.php\?uid=\d*\'>(?P<univer>[^<]*)</a>').search(lines)
#        if m and m.group('univer'):
#            pdata.univer=m.group('univer').rstrip().lstrip()
        
      
        # Ищем типичную информацию. По типу label, value, url
#        regex=re.compile('<td class=[^>]*>(?P<label>[^:]*):</td>\s*<td class=[^>]*>\s*<div class=[^>]*>\s*<a href=\'(?P<url>[^\']*)\'>(?P<value>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            if  m.group('url') and  m.group('label') and  m.group('value'):
#                info=InfoData(
#                                m.group('url'),
#                                m.group('label'),
#                                m.group('value')
#                                )
#                info.members[pdata.idnum]=pdata
#                pdata.infos[info.label]=info
#            m=regex.search(lines,m.end())
#        
#        # Забиваем найденные данные в поля персоны
#        infos = pdata.infos
#        for key in infos.keys():
#            if key == "Пол":
#                pdata.sex = infos[key].value
#            elif key == "Семейное положение":
#                pdata.marrige = infos[key].value
#            elif key == "Родной город":
#                pdata.city = infos[key].value
#            elif key == "Полит. взгляды":
#                pdata.politic = infos[key].value
#            elif key == "Религ. взгляды":
#                pdata.religion = infos[key].value
#            elif key == "Деятельность":
#                pdata.doing = infos[key].value
#            elif key == "Факультет":
#                pdata.faculty = infos[key].value
#            elif key == "Кафедра":
#                pdata.department = infos[key].value
#            elif key == "Форма обучения":
#                pdata.edutype = infos[key].value
#            elif key == "Статус":
#                pdata.status = infos[key].value
#        # Отпарсим день рождения
#        m = re.compile('<a href=\'search.php\?day=(?P<day>\d*)&month=(?P<month>\d*)\'>[^<]*</a> <a href=[^>]*>(?P<year>\d*)</a>').search(lines)
#        if m:
#                pdata.birthday['day']=m.group('day').rstrip().lstrip()
#                pdata.birthday['month']=m.group('month').rstrip().lstrip()
#                pdata.birthday['year']=m.group('year').rstrip().lstrip()
#         
#        # Ищем типичную информацию. По типу label, value
#        regex=re.compile('<td class=[^>]*>(?P<label>[^:]*):</td>\s*<td class=[^>]*>\s*<div class=[^>]*>\s*(?P<value>[^<]*)</div>')
#        m=regex.search(lines)
#        while m:
#            if  m.group('label') and  m.group('value'):
#                info=InfoData(
#                                "",
#                                m.group('label'),
#                                m.group('value')
#                                )
#                info.members[pdata.idnum]=pdata
#                pdata.infos[info.label]=info
#            m=regex.search(lines,m.end())
#        # Забиваем найденные данные в поля персоны
#        infos = pdata.infos
#        for key in infos.keys():
#            if key == "Моб. телефон":
#                if not ("Информация скрыта" in infos[key].value):
#                    pdata.mobile = infos[key].value
#                else: 
#                    pdata.mobile = "скрыто"
#            if key == "Дом. телефон":
#                if not ("Информация скрыта" in infos[key].value):
#                    pdata.home_tel = infos[key].value
#                else: 
#                    pdata.home_tel = "скрыто"
#            if key == "ICQ":
#                if not ("Информация скрыта" in infos[key].value):
#                    pdata.icq = infos[key].value
#                else: 
#                    pdata.icq = "скрыто"
#        # Ищем Веб сайт
#        m = re.compile('<a href=\'http://vkontakte\.ru/away\.php\?to=(?P<url>[^\']*)\' target=\'_blank\'>(?P<name>[^<]*)</a>').search(lines)
#        if m:
#                pdata.web['name']=m.group('name').rstrip().lstrip()
#                pdata.web['url']=m.group('url').rstrip().lstrip()
#        # Ищем Мобильник
#        regex = re.compile('<td class=[^>]*>Моб. телефон:</td>\s*<td class=[^>]*>\s*<div class=[^>]*>\s*(?P<mobile>.*)\s*</div>')
#        m=regex.search(lines)
#        if m:
#            if not ("Информация скрыта" in m.group('mobile')):
#                pdata.mobile=m.group('mobile').rstrip().lstrip()
#        # Поиск интересов
#        regex=re.compile('<a href=\'search.php\?f=1&f2=[^\']*\'>(?P<name>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            name=m.group('name').lower().lstrip().rstrip()
#            if len(name)>0:
#                inter=Interest(name)
#                inter.members[pdata.idnum]=pdata
#                pdata.interests[inter.name]=inter
#            m=regex.search(lines,m.end())
#        # Поиск любимой музыки
#        regex=re.compile('<a href=\'audio.php\?act=search&tabs=1&t=1&field=3&q=[^\']*\'>(?P<name>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            name=m.group('name').lower().lstrip().rstrip()
#            if len(name)>0:
#                inter=Interest(name)
#                inter.members[pdata.idnum]=pdata
#                pdata.music[inter.name]=inter
#            m=regex.search(lines,m.end())
#        # Поиск любимых фильмов
#        regex=re.compile('<a href=\'video.php\?act=search&tabs=1&t=1&field=4&q=[^\']*\'>(?P<name>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            name=m.group('name').lower().lstrip().rstrip()
#            if len(name)>0:
#                inter=Interest(name)
#                inter.members[pdata.idnum]=pdata
#                pdata.films[inter.name]=inter
#            m=regex.search(lines,m.end())
#        # Поиск любимых сериалов
#        regex=re.compile('<a href=\'video.php\?act=search&tabs=1&field=5&t=1&q=[^\']*\'>(?P<name>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            name=m.group('name').lower().lstrip().rstrip()
#            if len(name)>0:
#                inter=Interest(name)
#                inter.members[pdata.idnum]=pdata
#                pdata.tv[inter.name]=inter
#            m=regex.search(lines,m.end())
#        # Поиск любимых книжек
#        regex=re.compile('<a href=\'search.php\?f=1&f6=[^\']*\'>(?P<name>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            name=m.group('name').lower().lstrip().rstrip()
#            if len(name)>0:
#                inter=Interest(name)
#                inter.members[pdata.idnum]=pdata
#                pdata.books[inter.name]=inter
#            m=regex.search(lines,m.end())
#        # Поиск любимых игр
#        regex=re.compile('<a href=\'search.php\?f=1&f7=[^\']*\'>(?P<name>[^<]*)</a>')
#        m=regex.search(lines)
#        while m:
#            name=m.group('name').lower().lstrip().rstrip()
#            if len(name)>0:
#                inter=Interest(name)
#                inter.members[pdata.idnum]=pdata
#                pdata.games[inter.name]=inter
#            m=regex.search(lines,m.end())
#        # Ищем цитаты
#        regex = re.compile('<td class=\"label\">Любимые цитаты:</td>\s*<td class=\"data\">\s*<div class=\"dataWrap\">\s*(?P<cit>.*)\s*</div>')
#        m = regex.search(lines)
#        if m:
#            pdata.citate=m.group('cit').rstrip().lstrip()
#        # Ищем раздел О себе
#        regex = re.compile('<td class=\"label\">О себе:</td>\s*<td class=\"data\">\s*<div class=\"dataWrap\">\s*(?P<am>.*)\s*</div>')
#        m=regex.search(lines)
#        if m:
#            pdata.aboutme=m.group('am').rstrip().lstrip()
#        # Запарсим все образования в один файл. пока
#        regex = re.compile('<div id=\"edu\" class=[^>]*>(.*)<div id=\"\S*\" class=\"flexOpen\">', re.S)
#        m=regex.search(lines)
#        if m:
#            match = m.groups()
#            html=match[0].rstrip().lstrip()
#            pdata.education = self.text_extractor(html=html)
#        # Запарсим всю карьеру в один файл пока
#        regex = re.compile('<div id=\"career\" class=[^>]*>(.*)<div id=\"\S*\" class=\"flexOpen\">', re.S)
#        m=regex.search(lines)
#        if m:
#            match = m.groups()
#            html=match[0].rstrip().lstrip()
#            pdata.career = self.text_extractor(html=html)
#        # Запарсим все места в один файл пока
#        regex = re.compile('<div id=\"places\" class=[^>]*>(.*)<div id=\"\S*\" class=\"flexOpen\">', re.S)
#        m=regex.search(lines)
#        if m:
#            match = m.groups()
#            html=match[0].rstrip().lstrip()
#            pdata.places = self.text_extractor(html=html)
#        


#fpage = open('c:/news.htm','r')
#p = VkontakteNewsParser()
#p.parse(fpage)